package cn.com.zero.manager.auth.service.impl;

import cn.com.zero.api.auth.po.MenuPO;
import cn.com.zero.api.message.dubbo.IMessageService;
import cn.com.zero.base.util.SensitiveInfoUtil;
import cn.com.zero.common.auth.security.po.AuthUserPO;
import cn.com.zero.common.auth.security.po.ErrorLoginLogPO;
import cn.com.zero.common.auth.security.po.LoginLogPO;
import cn.com.zero.common.auth.security.service.AbstractLoginAuthenticationService;
import cn.com.zero.manager.auth.constant.ManagerAuthConstants;
import cn.com.zero.manager.auth.enums.LogStatusEnum;
import cn.com.zero.manager.auth.enums.LogTypeEnum;
import cn.com.zero.manager.auth.mapper.ILoginAuthenticationMapper;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import org.apache.dubbo.config.annotation.DubboReference;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestAttributes;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;
import java.util.Date;
import java.util.List;

/**
 * @author guoxin
 * @version 1.0.0
 * @Description
 * @date 2023/3/31 13:59
 */
@Component
public class LoginAuthenticationService extends AbstractLoginAuthenticationService {

    private ILoginAuthenticationMapper loginAuthenticationMapper;

    private IMessageService messageService;

    @Override
    public String getAuthenticationSide() {
        return ManagerAuthConstants.MANAGER_SIDE_NAME;
    }

    @Override
    public AuthUserPO getUserByMobile(String mobile) {
        String encrypt = SensitiveInfoUtil.encryptMobile(mobile);
        AuthUserPO authUserPO = loginAuthenticationMapper.selectUserByMobile(encrypt);
        if(ObjectUtil.isNull(authUserPO)){
            return null;
        }
        authUserPO.setMobile(mobile);
        authUserPO.setLoginIp(getRealRequestIp());
        authUserPO.setLoginTime(new Date());
        return authUserPO;
    }

    @Override
    public AuthUserPO getUserByNameOrMobile(String userName) {
        AuthUserPO authUserPO = loginAuthenticationMapper.selectUserByUserName(userName);
        if(ObjectUtil.isNull(authUserPO)){
            return null;
        }
        authUserPO.setMobile(SensitiveInfoUtil.decryptMobile(authUserPO.getMobile()));
        authUserPO.setLoginIp(getRealRequestIp());
        authUserPO.setLoginTime(new Date());
        return authUserPO;
    }

    @Override
    public List<MenuPO> getMenusByUserId(String userId) {
        return loginAuthenticationMapper.selectMenuByUserId(userId);
    }

    @Override
    public Long checkLoginVerificationCode(String mobile, String verificationCode) {
        return messageService.checkVerificationCode(mobile,
                ManagerAuthConstants.LOGIN_VERIFICATION_CODE_MESSAGE_TYPE, verificationCode);
    }

    @Override
    protected void modifyUserInfo(AuthUserPO userPO) {
        String encode = "";
        if(!StrUtil.isBlank(userPO.getPassword())){
            userPO.setPassword(SensitiveInfoUtil.encryptPwd(userPO.getPassword()));
        }
        if(!StrUtil.isBlank(userPO.getMobile())){
            userPO.setMobile(SensitiveInfoUtil.encryptMobile(userPO.getMobile()));
            encode = SensitiveInfoUtil.encode(userPO.getMobile(), 3, 7);
        }
        if(!ObjectUtil.isNull(loginAuthenticationMapper.isExistUserByMobile(userPO)) ||
        !ObjectUtil.isNull(loginAuthenticationMapper.isExistUserByUserName(userPO))){
            return;
        }
        loginAuthenticationMapper.modifyUserInfo(userPO, String.valueOf(encode));
    }

    @Override
    protected void deleteErrorLoginLog(String userId) {
        loginAuthenticationMapper.DeleteErrorLogin(userId);
    }

    @Override
    protected void addUserLoginLog(LoginLogPO loginLogPO) {
        LoginLogPO logPO = loginAuthenticationMapper.selectLoginLog(loginLogPO.getUserId());
        if(!ObjectUtil.isNull(logPO)){
            loginAuthenticationMapper.updateManager(logPO.getLoginTime(),logPO.getLoginIp(),loginLogPO.getUserId());
        }
        loginAuthenticationMapper.addUserLoginLog(loginLogPO, LogTypeEnum.getValueByName(loginLogPO.getType()),
                LogStatusEnum.getValueByName(loginLogPO.getResult()),
                Integer.valueOf(loginLogPO.getLoginDevice()));
    }

    @Override
    protected int getErrorLoginTimes(String userId) {
        Integer errorLoginTimes = loginAuthenticationMapper.getErrorLoginTimes(userId);
        if(null == errorLoginTimes){
            return 0;
        }
        return errorLoginTimes;
    }

    @Override
    protected void addUserErrorLoginLog(ErrorLoginLogPO errorLoginLogPO) {
        Integer errorLoginTimes = loginAuthenticationMapper.getErrorLoginTimes(errorLoginLogPO.getUserId());
        if (null == errorLoginTimes){
            loginAuthenticationMapper.insertErrorLogin(errorLoginLogPO.getUserId());
        }
        else {
            errorLoginTimes++;
            loginAuthenticationMapper.updateErrorLogin(errorLoginLogPO.getUserId(),errorLoginTimes);
        }

    }

    @Autowired
    public void setLoginAuthenticationMapper(ILoginAuthenticationMapper loginAuthenticationMapper) {
        this.loginAuthenticationMapper = loginAuthenticationMapper;
    }

    @DubboReference
    public void setMessageService(IMessageService messageService) {
        this.messageService = messageService;
    }

    /**
     * 获取IP地址
     *
     * @return
     */
    private String getRealRequestIp() {
        RequestAttributes requestAttributes = RequestContextHolder.getRequestAttributes();
        HttpServletRequest request = ((ServletRequestAttributes) requestAttributes).getRequest();
        String ip = request.getHeader("x-forwarded-for");
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeader("Proxy-Client-IP");
        }
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeader("WL-Proxy-Client-IP");
        }
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeader("HTTP_CLIENT_IP");
        }
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeader("HTTP_X_FORWARDED_FOR");
        }
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getRemoteAddr();
        }
        if (null != ip && ip.contains(",")) {
            ip = ip.substring(0, ip.indexOf(","));
        }
        return ip;
    }
}
